package com.silverhaze.diamond.client.utils.export;

import com.silverhaze.diamond.common.entity.SystemUser;
import com.silverhaze.diamond.common.entity.Customer;
import com.silverhaze.diamond.common.entity.Service;
import jxl.Workbook;
import jxl.read.biff.BiffException;
import jxl.write.Label;
import jxl.write.WritableSheet;
import jxl.write.WritableWorkbook;
import jxl.write.WriteException;

import java.io.File;
import java.io.IOException;
import java.util.*;

/**
 * SystemUser: Babanin
 * Date: 14.09.2008
 * Time: 11:42:12
 */
public class ExcelExporter {
    public static final String TEMPLATE_EXCEL_DOC = "data\\template\\document.xls";

    public static String[] MONTHS = new String[]{"Января", "Февраля", "Марта", "Апреля", "Мая", "Июня", "Июля",
            "Августа", "Сентября", "Октября", "Ноября", "Декабря"};

    private static final Point NUMBER_OF_ORDER = new Point(3, 5);
    private static final Point NUMBER_OF_ORDER2 = new Point(34, 5);

    private static final Point FROM_DATE = new Point(3, 7);
    private static final Point FROM_DATE2 = new Point(34, 7);

    private static final Point TECHNICS = new Point(4, 5);
    private static final Point TECHNICS2 = new Point(35, 5);

    private static final Point CUSTOMER = new Point(5, 1);
    private static final Point CUSTOMER2 = new Point(36, 1);

    private static final Point TELEPHONE = new Point(5, 7);
    private static final Point TELEPHONE2 = new Point(36, 7);

    private static final Point ADDRESS = new Point(6, 1);
    private static final Point ADDRESS2 = new Point(37, 1);

    private static final Point MODEL = new Point(7, 2);
    private static final Point MODEL2 = new Point(38, 2);

    private static final Point TECH_MODEL = new Point(8, 4);
    private static final Point TECH_MODEL2 = new Point(39, 4);

    private static final Point SERIAL_NUMBER = new Point(9, 2);
    private static final Point SERIAL_NUMBER2 = new Point(40, 2);

    private static final Point DATE = new Point(10, 2);
    private static final Point DATE2 = new Point(41, 2);

    private static final Point STAMP_STATUS = new Point(10, 7);
    private static final Point STAMP_STATUS2 = new Point(41, 7);

    private static final Point GUARANTY_TICKET = new Point(11, 2);
    private static final Point GUARANTY_TICKET2 = new Point(42, 2);

    private static final Point COMPLETENESS = new Point(11, 7);
    private static final Point COMPLETENESS2 = new Point(42, 7);

    private static final Point CUSTOMER_COMMENTS = new Point(13, 5);
    private static final Point CUSTOMER_COMMENTS_NEXT = new Point(14, 0);

    private static final Point CUSTOMER_COMMENTS2 = new Point(44, 5);
    private static final Point CUSTOMER_COMMENTS_NEXT2 = new Point(45, 0);

    private static final Point MASTER_COMMENTS = new Point(16, 3);
    private static final Point MASTER_COMMENTS_NEXT = new Point(17, 0);

    private static final Point MASTER_COMMENTS2 = new Point(47, 3);
    private static final Point MASTER_COMMENTS_NEXT2 = new Point(48, 0);

    private static final int COMMENT_FIRST_LINE_LENGTH = 45;
    private static final int COMMENT_NEXT_LINES_LENGTH = 95;

    public static void export(File exportFile, Service service) throws BiffException {
        try {
            Workbook templateWorkbook = Workbook.getWorkbook(new File(TEMPLATE_EXCEL_DOC));
            WritableWorkbook workbook = Workbook.createWorkbook(exportFile, templateWorkbook);
            WritableSheet sheet = workbook.getSheet(0);

            fillWithData(sheet, service);

            workbook.write();
            workbook.close();
        } catch (IOException e) {
            throw new RuntimeException(e);
        } catch (WriteException e) {
            throw new RuntimeException(e);
        }
    }

    private static void fillWithData(WritableSheet sheet, Service service) throws WriteException {
        List<Label> labels = new ArrayList<Label>();

        labels.add(new Label(NUMBER_OF_ORDER.getColumn(), NUMBER_OF_ORDER.getRow(), "" + service.getId()));
        labels.add(new Label(NUMBER_OF_ORDER2.getColumn(), NUMBER_OF_ORDER2.getRow(), "" + service.getId()));

        String fromDateString = formatDate(service.getDateService());
        labels.add(new Label(FROM_DATE.getColumn(), FROM_DATE.getRow(), fromDateString));
        labels.add(new Label(FROM_DATE2.getColumn(), FROM_DATE2.getRow(), fromDateString));

        labels.add(new Label(TECHNICS.getColumn(), TECHNICS.getRow(), "" + service.getTechNames()));
        labels.add(new Label(TECHNICS2.getColumn(), TECHNICS2.getRow(), "" + service.getTechNames()));

        labels.add(new Label(CUSTOMER.getColumn(), CUSTOMER.getRow(), "" + service.getOwner().getExtendedName()));
        labels.add(new Label(CUSTOMER2.getColumn(), CUSTOMER2.getRow(), "" + service.getOwner().getExtendedName()));

        labels.add(new Label(TELEPHONE.getColumn(), TELEPHONE.getRow(), "" + service.getOwner().getPhone()));
        labels.add(new Label(TELEPHONE2.getColumn(), TELEPHONE2.getRow(), "" + service.getOwner().getPhone()));

        labels.add(new Label(ADDRESS.getColumn(), ADDRESS.getRow(), "" + service.getOwner().getAddress()));
        labels.add(new Label(ADDRESS2.getColumn(), ADDRESS2.getRow(), "" + service.getOwner().getAddress()));

        labels.add(new Label(MODEL.getColumn(), MODEL.getRow(), "" + service.getModelName()));
        labels.add(new Label(MODEL2.getColumn(), MODEL2.getRow(), "" + service.getModelName()));

        labels.add(new Label(TECH_MODEL.getColumn(), TECH_MODEL.getRow(), "" + service.getTechModelName()));
        labels.add(new Label(TECH_MODEL2.getColumn(), TECH_MODEL2.getRow(), "" + service.getTechModelName()));

        labels.add(new Label(SERIAL_NUMBER.getColumn(), SERIAL_NUMBER.getRow(), "" + service.getSerialNumber()));
        labels.add(new Label(SERIAL_NUMBER2.getColumn(), SERIAL_NUMBER2.getRow(), "" + service.getSerialNumber()));

        String addressString = formatDate(service.getDateProduce());
        labels.add(new Label(DATE.getColumn(), DATE.getRow(), "" + addressString));
        labels.add(new Label(DATE2.getColumn(), DATE2.getRow(), "" + addressString));

        labels.add(new Label(STAMP_STATUS.getColumn(), STAMP_STATUS.getRow(), "" + service.getStampState()));
        labels.add(new Label(STAMP_STATUS2.getColumn(), STAMP_STATUS.getRow(), "" + service.getStampState()));

        labels.add(new Label(GUARANTY_TICKET.getColumn(), GUARANTY_TICKET.getRow(), "" + service.getGuarantyId()));
        labels.add(new Label(GUARANTY_TICKET2.getColumn(), GUARANTY_TICKET2.getRow(), "" + service.getGuarantyId()));

        labels.add(new Label(COMPLETENESS.getColumn(), COMPLETENESS.getRow(), "" + service.getCompleteness()));
        labels.add(new Label(COMPLETENESS2.getColumn(), COMPLETENESS2.getRow(), "" + service.getCompleteness()));

        List<String> customerComments = split(service.getOwnerDefect());
        if (customerComments.size() > 0) {
            labels.add(new Label(CUSTOMER_COMMENTS.getColumn(), CUSTOMER_COMMENTS.getRow(), customerComments.get(0)));
            labels.add(new Label(CUSTOMER_COMMENTS2.getColumn(), CUSTOMER_COMMENTS2.getRow(), customerComments.get(0)));

            if (customerComments.size() > 1) {
                labels.add(new Label(CUSTOMER_COMMENTS_NEXT.getColumn(), CUSTOMER_COMMENTS_NEXT.getRow(), customerComments.get(1)));
                labels.add(new Label(CUSTOMER_COMMENTS_NEXT2.getColumn(), CUSTOMER_COMMENTS_NEXT2.getRow(), customerComments.get(1)));

                if (customerComments.size() > 2) {
                    labels.add(new Label(CUSTOMER_COMMENTS_NEXT.getColumn(), CUSTOMER_COMMENTS_NEXT.getRow() + 1, customerComments.get(2)));
                    labels.add(new Label(CUSTOMER_COMMENTS_NEXT2.getColumn(), CUSTOMER_COMMENTS_NEXT2.getRow() + 1, customerComments.get(2)));
                }
            }
        }

        List<String> masterComments = split(service.getMasterDefect());
        if (masterComments.size() > 0) {
            labels.add(new Label(MASTER_COMMENTS.getColumn(), MASTER_COMMENTS.getRow(), masterComments.get(0)));
            labels.add(new Label(MASTER_COMMENTS2.getColumn(), MASTER_COMMENTS2.getRow(), masterComments.get(0)));

            if (masterComments.size() > 1) {
                labels.add(new Label(MASTER_COMMENTS_NEXT.getColumn(), MASTER_COMMENTS_NEXT.getRow(), masterComments.get(1)));
                labels.add(new Label(MASTER_COMMENTS_NEXT2.getColumn(), MASTER_COMMENTS_NEXT2.getRow(), masterComments.get(1)));

                if (masterComments.size() > 2) {
                    labels.add(new Label(MASTER_COMMENTS_NEXT.getColumn(), MASTER_COMMENTS_NEXT.getRow() + 1, masterComments.get(2)));
                    labels.add(new Label(MASTER_COMMENTS_NEXT2.getColumn(), MASTER_COMMENTS_NEXT2.getRow() + 1, masterComments.get(2)));
                }
            }
        }

        for (Label label : labels) {
            sheet.addCell(label);
        }
    }

    private static List<String> split(String defect) {
        List<String> result = new ArrayList<String>();

        int maxSize = COMMENT_FIRST_LINE_LENGTH;
        String[] words = defect.split(" ");
        StringBuilder builder = new StringBuilder();
        for (String word : words) {
            if (builder.length() + word.length() <= maxSize) {
                builder.append(word).append(" ");
            } else {
                maxSize = COMMENT_NEXT_LINES_LENGTH;
                result.add(builder.toString());
                builder = new StringBuilder();
                builder.append(word).append(" ");
            }
        }
        result.add(builder.toString());

        return result;
    }

    private static String formatDate(Date dateProduce) {
        if (dateProduce == null) {
            dateProduce = new Date();
        }

        GregorianCalendar calendar = new GregorianCalendar();
        calendar.setTime(dateProduce);

        StringBuilder builder = new StringBuilder();

        builder.append(calendar.get(Calendar.DAY_OF_MONTH)).append(" ");
        builder.append(MONTHS[calendar.get(Calendar.MONTH)]).append(" ");
        builder.append(calendar.get(Calendar.YEAR)).append(" г.");

        return builder.toString();
    }

    public static void main(String[] args) throws BiffException {
//        export("C:\\data.xls", generateCustomService());
    }

    private static Service generateCustomService() {
        Service service = new Service();

        Customer customer = new Customer();
        customer.setPhone("+7 927 00 777 65");
        customer.setAddress("ул. Чапаева д. 42");
        customer.setId(1L);
        customer.setName("Иван");
        customer.setPatronymic("Олегович");
        customer.setSurname("Бабанин");

        service.setSystemUser(new SystemUser());
        service.setDateProduce(new Date());
        service.setTechNames(generateSomeString());
        service.setTechModelName(generateSomeString());
        service.setStampState(generateSomeString());
        service.setSerialNumber(generateSomeString());
        service.setOwnerDefect(generateSomeString());
        service.setMasterDefect(generateSomeString());
        service.setOwner(customer);
        service.setModelName(generateSomeString());
        service.setGuarantyId(generateSomeString());
        service.setCompleteness(generateSomeString());

        return service;
    }

    private static String generateSomeString() {
        Random random = new Random();

        int aCh = 'a';
        StringBuilder builder = new StringBuilder();
        int wordSize = Math.abs(random.nextInt()) % 10 + 5;
        for (int i = 0; i < wordSize; i++) {
            builder.append((char) (aCh + random.nextInt() % 10 + 10));
        }

        return builder.toString();
    }

    private static int generateSomeNumber(int size) {
        return new Random().nextInt(size);
    }

    static class Point {
        int row;
        int column;

        Point(int row, int column) {
            this.row = row;
            this.column = column;
        }

        public int getRow() {
            return row;
        }

        public int getColumn() {
            return column;
        }
    }
}

